package com.bieber.smartpost.invoke.filter.filler;

import com.bieber.smartpost.httpcore.Response;
import com.bieber.smartpost.invoke.FilterChain;
import com.bieber.smartpost.invoke.FilterContext;
import com.bieber.smartpost.invoke.filter.AbstractFilter;
import com.bieber.smartpost.model.RequestEntity;
import com.bieber.smartpost.util.Utils;
import com.jbeer.framework.exception.JBeerException;
import com.jbeer.framework.utils.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by bieber on 14-11-30.
 */
public abstract class BasicFiller<T extends Object> extends AbstractFilter{


    private static final Pattern INDEX_PATTERN = Pattern.compile("\\[[0-9]+\\]");

    private static final Pattern DEFAULT_PATTERN = Pattern.compile("\\[default:[\\w\\/\\\"\\\\\\{\\}\\[\\]\\+\\-\\*:,\\.\\u4e00-\\u9fa5]{0,}\\]");

    protected  static final String DEFAULT_VALUE_REGEX="(\\[default:[\\w\\/\\\"\\\\\\{\\}\\[\\]\\+\\-\\*:,\\.\\u4e00-\\u9fa5]{0,}\\]){0,1}";

    protected  static final String INDEX_REGEX="(\\[[0-9]{1}[0-9]*\\])";

    protected static final String EMPTY_STRING="";
    /**
     * 此处讲Filter转化成filler模式，屏蔽filter的方法，从而可以使得filler之关注filler的功能，
     * 而无需关注Filter
     * @param chain
     * @param entity
     */
    public final void doFilter(FilterChain chain, RequestEntity entity) {
        commonFill(entity,chain.getContext());
        chain.doChain(entity);
    }

    protected  void commonFill(RequestEntity entity,FilterContext context){
        //此处表示当前处理的请求是第一个，还没有上一个响应实体，所以不用进行填充参数
        if(context.getLastResponse().isEmpty()||entity==null){
            return ;
        }
        try {
            fillRequestParameters(entity, context);
            if(entity.getHeader()!=null&&entity.getHeader().size()>0){
                fillRequestHeader(entity,context);
            }
            fillRequestUrl(entity,context);
        } catch (IOException e) {
            Utils.COMMONS_LOGGER.debug("filler error ", e);
        } catch (JBeerException e) {
            Utils.COMMONS_LOGGER.debug("filler error ", e);
        }
    }


    protected List<FillerRule> generateFillerRule(Pattern pattern,String content){
        Matcher matcher = pattern.matcher(content);
        Pattern expressionPattern = Pattern.compile(getExpressionRegex());
        String ruleGroup = null;
        Matcher indexMatcher;
        Matcher defaultMatcher;
        String type=null;
        String expression=null;
        Integer index=null;
        String indexStr;
        String defaultStr=null;
        List<FillerRule> rules = new ArrayList<FillerRule>();
        while(matcher.find()){
            ruleGroup = matcher.group();

            Matcher expressionMatcher = expressionPattern.matcher(ruleGroup);
            //matched expression 'xxxx'
            if(expressionMatcher.find()){
                expression=expressionMatcher.group();
            }else{
                throw new IllegalArgumentException("not found expression from "+ruleGroup);
            }
            //matched #{json:
            type=ruleGroup.substring(0,ruleGroup.indexOf(expression));
            type=type.substring(2,type.length()-1);
            ruleGroup=ruleGroup.substring(ruleGroup.indexOf(expression)+expression.length());
            //matched [01]
            indexMatcher = INDEX_PATTERN.matcher(ruleGroup);
            if(indexMatcher.find()){
                indexStr =  indexMatcher.group();
                indexStr=indexStr.substring(1,indexStr.length()-1);
                index = new BigDecimal(indexStr).intValue();
            }
            //matched [default:xxxx]
            defaultMatcher = DEFAULT_PATTERN.matcher(ruleGroup);
            defaultMatcher.groupCount();
            if(defaultMatcher.find()){
                defaultStr=defaultMatcher.group();
                defaultStr = defaultStr.substring(9,defaultStr.length()-1);
            }
            expression=expression.substring(1,expression.length()-1);
            rules.add(new FillerRule(FillerRule.RuleType.getType(type),expression,index,defaultStr));
            index=null;
            expression=null;
            defaultStr=null;
        }
        return rules;
    }


    protected abstract String getExpressionRegex();

    /**
     * 留给子类实现的filler的接口，处理filler相关业务
     * @param entity
     * @param context
     */
    private  void fillRequestParameters(RequestEntity entity, FilterContext context) throws IOException, JBeerException{
        if(entity.getParams()==null){
            return ;
        }
        Response lastResponse = context.getLastResponse();
        if(!StringUtils.isEmpty(lastResponse.getResponseContent())){
            T dataSource = generateDataSource(context);
            if("form".equalsIgnoreCase(entity.getParametersType())){//说明时map
                Map<String,String> paramsMap = (Map<String, String>) entity.getParams();
                for(Map.Entry<String,String> entry:paramsMap.entrySet()){
                    entry.setValue(convertValue(entry.getValue(),dataSource));
                }
                entity.setParams(paramsMap);
            }else{
                String paramsStr = entity.getParams().toString();
                paramsStr=convertValue(paramsStr,dataSource);
                entity.setParams(paramsStr);
            }
        }
    }


    private void fillRequestHeader(RequestEntity entity,FilterContext context) throws IOException, JBeerException{
        Response lastResponse = context.getLastResponse();
        if(!StringUtils.isEmpty(lastResponse.getResponseContent())){
            T dataSource = generateDataSource(context);
            List<Map<String,String>> headers = entity.getHeader();
            for(Map<String,String> header:headers){
                for(Map.Entry<String,String> entry:header.entrySet()){
                    entry.setValue(convertValue(entry.getValue(),dataSource));
                }
            }
            entity.setHeader(headers);
        }
    }

    private void fillRequestUrl(RequestEntity entity,FilterContext context) throws IOException, JBeerException{
        Response lastResponse = context.getLastResponse();
        if(!StringUtils.isEmpty(lastResponse.getResponseContent())){
            T dataSource = generateDataSource(context);
            entity.setUrl(convertValue(entity.getUrl(),dataSource));
        }
    }

    protected abstract String convertValue(String originValue,T object) throws JBeerException;


    protected abstract T generateDataSource(FilterContext context) throws IOException, JBeerException;
    /**
     * filler默认情况无先后顺序，所以order相同
     * @return
     */
    public int order() {
        return 2;
    }
}
